package com.itlong.cloud.intercept.sdkV1;

import com.alibaba.fastjson.JSONObject;
import com.itlong.cloud.POJO.PO.PropertyUserInfoPO;
import com.itlong.cloud.POJO.VO.MessageVO;
import com.itlong.cloud.enumerate.ecode.BaseErrorCodeEnum;
import com.itlong.cloud.enumerate.ecode.CloudTalkErrorCodeEnum;
import com.itlong.cloud.user.sdk.ICloudTalkSDKServerUserServiceClient;
import com.itlong.cloud.user.sdk.ISDKServerOldUserServiceClient;
import com.itlong.cloud.utils.encrypt.DesEncryptUtil;
import com.itlong.cloud.utils.encrypt.Md5EncryptUtil;
import com.itlong.cloud.utils.network.http.HttpProtocolUtil;
import com.itlong.cloud.utils.node.JsonUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <desc>
 * 云设备 入参处理拦截器
 * </desc>
 *
 * @createDate 2018/12/27
 */
@Aspect
@Component
public class CloudDeviceParamIntercept {
    private static Logger LOG = LoggerFactory.getLogger(CloudTalkSDKServerLoginIntercept.class);

    @Autowired
    ICloudTalkSDKServerUserServiceClient iCloudTalkSDKServerUserServiceClient;

    @Autowired
    ISDKServerOldUserServiceClient iSDKUserServiceClient;

    // 定义一个切入点
    @Pointcut("execution(* com.itlong.cloud.controller.sdkV1.cloud.elevator.server.*.*(..)) || execution(* com.itlong.cloud.controller.sdkV1.cloud.intercom.server.*.*(..))" +
            "|| execution(* com.itlong.cloud.controller.sdkV1.cloud.entrance.server.*.*(..))")
    public void excudeService() {
    }

    /**
     * <desc>
     * 云设备 入参解密验签拦截器
     * </desc>
     *
     * @param thisJoinPoint
     * @return
     * @author Qiang.S
     * @createDate 2018/12/27
     */
    @Around("excudeService()")
    public Object twiceAsOld(ProceedingJoinPoint thisJoinPoint) throws Throwable {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        String appId = request.getParameter("appId");
        PropertyUserInfoPO propertyUserInfoPO = iSDKUserServiceClient.getPropertyUserByAppId(appId);
        if (propertyUserInfoPO == null) { //appId 错误导致无法查询出开发者信息
            return new MessageVO(BaseErrorCodeEnum.PARAM_ERR.getErrorCode());//此时没有加密签名直接明文返回报错信息
        }
        try {
            //入参密文
            String encryptScript = request.getParameter("encryptScript");

            if (StringUtils.isBlank(encryptScript)) { //加密串未携带，参数异常
                return getEncryptResult(new MessageVO(BaseErrorCodeEnum.PARAM_ERR.getErrorCode()), propertyUserInfoPO.getAppsecret());
            } else {
                //解密入参
                String encryptResult = DesEncryptUtil.aesDecrypt(encryptScript, propertyUserInfoPO.getAppsecret());
                encryptResult = encryptResult.replaceAll("&quot;","\"");
                if (encryptResult == null) {
                    return getEncryptResult(new MessageVO(BaseErrorCodeEnum.PARAM_ERR.getErrorCode()), propertyUserInfoPO.getAppsecret());
                }
                //验签
                JSONObject jsStr = JSONObject.parseObject(encryptResult);//入参转json
                Map<String, Object> params = JsonUtil.toObject(encryptResult, HashMap.class);//入参转map
                String sign = jsStr.get("sign").toString();
                String appSecret = jsStr.get("appSecret").toString();
                params.remove("sign");//移除签名
                params.remove("appSecret");//移除密码
                if (!Md5EncryptUtil.checkCloudTalkSDKSign(params, sign, propertyUserInfoPO.getAppsecret())) {
                    return getEncryptResult(new MessageVO(CloudTalkErrorCodeEnum.SERVER_MD5_ERROR.getErrorCode()), propertyUserInfoPO.getAppsecret());
                }
                Map<String, Object> paramsObject = JsonUtil.toObject(encryptResult, HashMap.class);//入参转map
                HttpProtocolUtil.setRequestAttributes(paramsObject, request);
                //通过appId appSecret来进行服务认证
                if (StringUtils.isNotBlank(appId) && StringUtils.isNotBlank(appSecret)) {
                    if (iCloudTalkSDKServerUserServiceClient.sdkServerLogin(appId, appSecret) > 0) {
                        // 校验开发者账号是否有该项目的权限
                        List<String> projectIdList = iCloudTalkSDKServerUserServiceClient.getProjectIdByParams(appId);
                        if (projectIdList == null || projectIdList.isEmpty() || !projectIdList.contains(params.get("projectId"))) {
                            return getEncryptResult(new MessageVO(CloudTalkErrorCodeEnum.SERVER_CHECKDEVELOPER_AUTH.getErrorCode()), propertyUserInfoPO.getAppsecret());
                        }
                        request.setAttribute("appId",propertyUserInfoPO.getUserId());
                        request.setAttribute("appSecret",propertyUserInfoPO.getAppsecret());
                        request.setAttribute("roleId",propertyUserInfoPO.getRoleId());
                        Object result = thisJoinPoint.proceed();
                        //加密
                        SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
                        Date date = new Date();
                        String createTime = df.format(date);
                        MessageVO messageVO = (MessageVO) result;
                        JSONObject json = JSONObject.parseObject(JsonUtil.toJSON(messageVO));
                        Map<String, Object> jsonToMap = new HashMap<>();
                        if (json != null) {
                            jsonToMap = JsonUtil.JsonToMap(json.toJSONString());
                        }else {
                            json = new JSONObject();
                            json.put("data","");
                        }
                        sign = Md5EncryptUtil.cloudDeviceMd5(jsonToMap,createTime,propertyUserInfoPO.getAppsecret());
                        json.put("createTime",createTime);
                        json.put("sign",sign);
                        Map<String, Object> resultMap = new HashMap<>();
                        resultMap.put("encryptScript", DesEncryptUtil.aesEncryptSDK(json.toJSONString(),propertyUserInfoPO.getAppsecret()));
                        return resultMap;
                    } else {
                        return getEncryptResult(new MessageVO(CloudTalkErrorCodeEnum.SERVER_DEVELOP_ERR.getErrorCode()), propertyUserInfoPO.getAppsecret());
                    }
                } else {
                    return getEncryptResult(new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode()), propertyUserInfoPO.getAppsecret());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return getEncryptResult(new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode()), propertyUserInfoPO.getAppsecret());
        }
    }

    /**
     * <desc>
     * 返回加密内容
     * </desc>
     *
     * @param appsecret 开发者用户密码
     * @return
     * @author Qiang.S
     * @createDate 2018/12/27
     */
    private Map<String, Object> getEncryptResult(Object result, String appsecret) throws Exception {
        MessageVO messageVO = (MessageVO) result;
        String encryptResult = DesEncryptUtil.aesEncryptSDK(JsonUtil.toJSON(messageVO),appsecret);
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("encryptScript", encryptResult);
        return resultMap;
    }
}